using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace GameFramework.Objects
{
    public enum TransitionState
    {
        TransitionOn,
        Active,
        TransitionOff,
        Hidden,
    }

    public abstract class TransitionObject : DrawableGameComponent
    {
        TransitionState _currentState;
        public TransitionState CurrentState
        {
            get
            {
                return _currentState;
            }
            set
            {
                _currentState = value;
            }
        }

        TimeSpan _transitionOnTime;
        public TimeSpan TransitionOnTime
        {
            get
            {
                return _transitionOnTime;
            }
            set
            {
                _transitionOnTime = value;
                TransitionOnTimeChanged(value);
            }
        }
        TimeSpan _activeTime;
        public TimeSpan ActiveTime
        {
            get
            {
                return _activeTime;
            }
            set
            {
                _activeTime = value;
            }
        }
        TimeSpan _transitionOffTime;
        public TimeSpan TransitionOffTime
        {
            get
            {
                return _transitionOffTime;
            }
            set
            {
                _transitionOffTime = value;
                TransitionOffTimeChanged(value);
            }        
        }

        public virtual void TransitionOffTimeChanged(TimeSpan value)
        {

        }

        public virtual void TransitionOnTimeChanged(TimeSpan value)
        {

        }

        float _transitionPosition;
        public float TransitionPosition
        {
            get
            {
                return _transitionPosition;
            }
            set
            {
                _transitionPosition = value;
            }
        }
                
        public float TransitionAlpha
        {
            get
            {
                return 1 - TransitionPosition;
            }            
        }

        private bool _unknownActiveTransitionTime = false;
        /// <summary>
        /// If your object waitting for some event on active, set this value true on Constructor or in EndTransitionOn method
        /// </summary>
        public bool UnknownActiveTransitionTime
        {
            get
            {
                return _unknownActiveTransitionTime;
            }
            set
            {
                _unknownActiveTransitionTime = value;
            }
        }


        public TransitionObject(Game game)
            : base(game)
        {            
            _transitionOnTime = TimeSpan.Zero;
            _transitionOffTime = TimeSpan.Zero;
            _activeTime = TimeSpan.Zero;
            Reset();
        }       

        public override void Update(GameTime gameTime)
        {
            if (!Enabled)
                return;

            switch (_currentState)
            {
                case TransitionState.TransitionOn:
                    if (UpdateTransition(gameTime, _transitionOnTime, -1))
                    {
                        _currentState = TransitionState.TransitionOn;
                        OnTransitonOn();
                    }
                    else
                    {                        
                        EndTransitionOn();
                        BeginActiveTransition();
                        _currentState = TransitionState.Active;
                    }
                    break;
                case TransitionState.Active:
                    if (_unknownActiveTransitionTime)
                    {
                        _currentState = TransitionState.Active;
                        OnUnknownActiveTransitionTime();
                    }
                    else
                    {
                        if (UpdateTransition(gameTime, _activeTime, 1))
                        {
                            _currentState = TransitionState.Active;
                            OnActiveTransition();
                        }
                        else
                        {
                            _currentState = TransitionState.TransitionOff;
                            EndActiveTransition();
                            BeginTransitionOff();
                        }
                    }
                    break;
                case TransitionState.TransitionOff:
                    if (UpdateTransition(gameTime, _transitionOffTime, -1))
                    {
                        _currentState = TransitionState.TransitionOff;
                        OnTransitionOff();
                    }
                    else
                    {
                        _currentState = TransitionState.Hidden;
                        EndTransitionOff();
                    }
                    break;
                case TransitionState.Hidden:
                    break;
            }

        }
       
        public virtual void Reset()
        {
            Enabled = false;
            Visible = false;
            _transitionPosition = 1;
            _currentState = TransitionState.TransitionOn;
        }

        public virtual void Start()
        {
            Reset();
            Enabled = true;
            Visible = true;
        }

        #region Transition Function
        public virtual void OnTransitonOn()
        {
        }

        public virtual void EndTransitionOn()
        {
        }

        public virtual void BeginActiveTransition()
        {
        }

        public virtual void OnActiveTransition()
        {
        }

        public virtual void OnUnknownActiveTransitionTime()
        {

        }

        public virtual void EndActiveTransition()
        {
        }

        public virtual void BeginTransitionOff()
        {
        }

        public virtual void OnTransitionOff()
        {
        }

        public virtual void EndTransitionOff()
        {
            Enabled = false;
            Visible = false;
        }
        #endregion

        /// <summary>
        /// true : Transition Completed
        /// </summary>
        /// <param name="gameTime"></param>
        /// <param name="time">duration time</param>
        /// <param name="direction">0->1:1 or 1->0:-1</param>
        /// <returns></returns>
        protected virtual bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
        {
            float transitionDelta;

            if (time == TimeSpan.Zero)
                transitionDelta = 1;
            else
                transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / time.TotalMilliseconds);

            _transitionPosition += transitionDelta * direction;//1->0 or 0->1

            if(((direction < 0)  && (_transitionPosition <=0)) ||
                ((direction > 0) && (_transitionPosition >=1)))
            {
                _transitionPosition = MathHelper.Clamp(_transitionPosition, 0, 1);
                return false;
            }

            return true;
        }
    }
}
